//用户
const config=require('../config');
let mongoose = require('mongoose');
let GameUserModel=mongoose.models['GameUser'];
class User{
    constructor(options,docker){
        this._id='';
        this.index=0; //用户在房间用户数组中的下标
        this.token='';
        this.nickname='';
        this.headImgUrl='';
        this.sex=0; //性别
        this.role=0; //角色
        this.level=0; //游戏段位数字
        this.group=0; //分组
        this.room=null;
        this.thumbtackCount=0; //手上图钉数量
        this.bombCount=2; //剩余炸弹数量
        this.bombColor=0; //默认的泡泡类型
        this.upX=-1; //上一次的横坐标  因为炸弹爆炸的时候，如果没有走到对应的格子，那么他的爆炸检测两个坐标都是起作用的
        this.upY=-1; //上一次的纵坐标
        this.x=0;
        this.y=0;
        this.power=1; //泡泡威力
        this.docker=docker;
        this.matchingGroup=null; //用户所在的匹配小组
        this.moveInterval=300; //移动1格间隔时间
        this.status=0;  //0停止状态  10被泡住  -1死亡
        this.properties=[]; //捡起的道具有哪些
        this.currentMessageCount=0; //当前用户的信息计数器，用于实现消息的先后顺序
        this.lastUpdateTick=new Date().getTime();
        this.isReady=false; //玩家是否准备好
        this.dieTimeTick=new Date().getTime();//死亡时间，如果死亡时间间隔游戏结束时间太久，则判断为输
        this.winCount=0;//连赢次数
        this.readyProp = '0|0|0';//游戏前视频购买的道具
        Object.assign(this,options);
        this.result=0; //游戏结果  1胜利  0平局  -1失败
        this.rewards=[]; //未领取的奖励  格式为[{type:0,count:10},{type:1,count:20}] 0代表钻石  1代表金币
        this.friendRoom=null; //好友房
    }
    async initUser(){
        let GameUserModel = mongoose.models['GameUser'];
        let gameUser = await GameUserModel.findById(this._id);
        if(!gameUser) return;
        let msg = gameUser.getMessage();
        Object.assign(this, msg);
        this.role = msg.usSkin;
        this.bombColor = msg.usPaopao;
    }
    //开始移动
    // startMove(){
    //     //this.moveTimer=setTimeout(this.move.bind(this),this.moveInterval);
    // }
    //房内广播
    roomBroadcast(dataObj={e:''}){
        if(!!this.room){
            this.room.broadcast(dataObj);
        }
    }
    //获取奖励
    getRewards(){
        //随机确定是出现观看视频获取双倍还是分享获取双倍
        let shareButton=false;
        let randomNumber=Math.random()*100;
        if(randomNumber>80){
            shareButton=true;
        }
        this.sendEvent('rewards',{rewards:this.rewards,shareButton:shareButton});
    }
    //领取奖励
    receiveRewards(){
        this._receiveRewards();
    }
    //双倍领取奖励
    receiveDoubleRewards(){
        this._receiveRewards(2);
    }

    //五倍领取奖励
    receiveFiveRewards(){
        this._receiveRewards(5);
    }
    //领取奖励
    async _receiveRewards(multiple=1){
        const mongoose=require('mongoose');
        let GameUserModel=mongoose.models['GameUser'];
        let gameUser=await GameUserModel.findById(this._id);
        console.log('gameUser ====', this._id, !!gameUser);
        if(!!gameUser&&gameUser.store){
            //N倍计算奖励
            for(let i=0;i<this.rewards.length;i++){
                this.rewards[i].count*=multiple;
            }
            //领取奖励
            gameUser.getGoods(this.rewards);
        }
        await gameUser.save();
        this.rewards=[];
    }
    //发送房内广播
    broadcastEvent(dataObj={eventName:'',data:{}}){
        dataObj.data._id=this._id;
        console.log('房间广播：',dataObj);
        if(!!this.room){
            this.room.broadcastEvent(dataObj.eventName,dataObj.data);
        }
    }
    //退出当前房间
    exitRoom(){
        if(this.status===-1){
            this.getFailReward();
            this.getRewards();
            this.room.broadcastEvent('exitRoom',{index:this.index});
            let User=require('./User');
            this.room.users[this.index]=new User(this.getMessage(),this.docker);
            this.reset();
        }
    }
    //如果该用户有房间，则直接返回房间信息
    getRoomMessage(){
        if(!!this.room){
            this.sendEvent('getRoomMessage',{data:this.room.getMessage()});
        }
    }
    //返回用户基本信息
    getMessage(){
        let obj={
            _id:this._id,
            x:this.x,
            y:this.y,
            role:this.role,
            sex:this.sex,
            group:this.group,
            nickname:this.nickname,
            headImgUrl:this.headImgUrl,
            status:this.status,
            moveInterval:this.moveInterval,
            bombCount:this.bombCount,
            thumbtackCount:this.thumbtackCount,
            isReady:this.isReady,
            level:this.level,
            winCount:this.winCount,
        };
        if(!!this.room){
            obj.roomId=this.room.roomId;
        }
        if(!!this.matchingGroup){
            obj.matchingGroupId=this.matchingGroup.groupId;
        }
        if(!!this.friendRoom){
            obj.friendRoomId=this.friendRoom.id;
        }
        return obj;
    }
    //判断该玩家是否有足够的钻石
    async hasDiamond(num){
        // const mongoose=require('mongoose');
        // let GameUserModel=mongoose.models['GameUser'];
        // let gameUser=await GameUserModel.findById(this._id);
        // if(!!gameUser&&gameUser.store.diamond>=num){
        //     return true;
        // }
        // return false;
        return true;
    }
    //检测钻石是否够，如果不够，发送钻石不足消息，并返回false
    async checkDiamond(num){
        // let hasDiamond=await this.hasDiamond(num);
        // if(!hasDiamond){
        //     this.sendEvent('notEnoughDiamonds',{msg:'钻石不足'});
        //     return false;
        // }
        return true;
    }
    //玩家加入某个房间
    joinRoom(room){
        this.room=room;
        room.users.push(this);
        this.index=this.room.users.findIndex(item=>{return item._id==this._id});
    }
    //加入游戏
    gameStartAdd(){
        let propArr = this.readyProp.split('|');
        this.bombCount += parseInt(propArr[0]);
        this.thumbtackCount += parseInt(propArr[1]);
        this.moveInterval -= parseInt(propArr[2]) > 0 ? 40 : 0;
    }
    //游戏开始扣除玩家消耗的钻石，判断该玩家是否可以携带飞镖
    async gameStartReduce(){
        const mongoose=require('mongoose');
        let GameUserModel=mongoose.models['GameUser'];
        let gameUser=await GameUserModel.findById(this._id);
        gameUser.readyProp = '0|0|0';
        await gameUser.save();
    }
    //获取胜利的奖励
    async getWinReward(){
        let gameUser=await GameUserModel.findById(this._id);
        if(!!gameUser){
            gameUser.goldCoin +=50;
            await gameUser.save();
        }
        //this.rewards=[{type:2,count:10}];
    }
    //获取平局的奖励
    async getTieReward(){
        let gameUser=await GameUserModel.findById(this._id);
        if(!!gameUser){
            gameUser.goldCoin +=10;
            await gameUser.save();
        }
        //this.rewards=[{type:2,count:5}];
    }
    //获取失败的奖励
    async getFailReward(){
        let gameUser=await GameUserModel.findById(this._id);
        if(!!gameUser){
            gameUser.goldCoin +=5;
            await gameUser.save();
        }
        //this.rewards=[{type:2,count:0}];
    }
    //玩家准备
    ready(){
        if(!this.room||this.isReady){
            return;
        }
        this.isReady=true;
        //检查所有玩家是否都已经准备好，如果准备好，则发送游戏准备事件
        if(this.room.users.findIndex(item=>{return item.isReady===false;})<0){
            this.room.status=1;
            //如果有自动准备定时器，则删除
            this.room.timerManager.clearTimeout(this.room.readyTimer);
            this.room.broadcastEvent('gameReady',{});
        }
    }
    setPos(data){
        if(this.status!==0){
            return;
        }
        if(data.n===0){
            this.upX=data.x;
            this.upY=data.y;
        }else{
            this.upX=this.x;
            this.upY=this.y;
        }
        this.x=data.x;
        this.y=data.y;
        //判断该位置是否有道具，如果有，则吃掉
        let property=this.room.properties.find(item=>{return item.x===this.x&&item.y===this.y});
        if(!!property){
            property.eat(this);
        }
        this.room.broadcast({e: 'move', i: this.index, n: data.n, x: this.x, y: this.y, t: this.moveInterval});
        //判断该位置是否有被泡住的玩家，如果有，让玩家死亡
        let bombedUsers=this.room.users.filter(item=>{return item.x===this.x&&item.y===this.y&&item.status===10&&item._id!==this._id});
        for(let i=0;i<bombedUsers.length;i++){
            if(bombedUsers[i].group===this.group){
                bombedUsers[i].beSalvation();
            }else{
                bombedUsers[i].die();
            }
        }
    }
    //是否是停止状态
    isStop(){
        return this.upX===this.x&&this.upY===this.y;
    }
    //停止移动
    moveStop(){
        this.upX=this.x;
        this.upY=this.y;
        if(this.status===0){
            if(!!this.room)
                this.room.broadcast({e:'moveStop',i:this.index});
        }
    }
    //被泡住
    beBomb(){
        if(!this.room){
            return;
        }
        this.changeStatus(10);
        this.moveStop();

        this.dieTimer=this.room.timerManager.setTimeout(function(){
            if(!this.room){
                return;
            }
            this.room.queue.pushTry(this.die.bind(this));
        }.bind(this),6000);
    }
    //使用图钉
    useThumbtack(){
        if(this.thumbtackCount>0&&this.status===10){
            this.thumbtackCount--;
            this.beSalvation();
        }
    }
    //被拯救
    beSalvation(){
        this.room.timerManager.clearTimeout(this.dieTimer);
        this.changeStatus(0);
    }
    //死亡
    die(){
        if(!this.room){return;}
        this.clearTimers();
        this.changeStatus(-1);
        this.dieTimeTick=new Date().getTime();
        //检测游戏结束
        this.room.timerManager.setTimeout(function(){
            if(!this.room){
                return;
            }
            this.room.queue.pushTry(this.room.checkGameOver.bind(this.room));
        }.bind(this),500);
    }
    bombProperties(){
        //获取玩家即将被爆出的道具

        let properties=[];
        let result=[];
        if(this.properties.length<3){
            properties=this.properties;
        }else{
            this.properties.sort((a,b)=>{return Math.random()-0.5;});
            properties=this.properties.splice(0,3);
        }
        //获取玩家附近没有障碍的三个空白点
        let posArray=[];
        for(let i=-3;i<=3;i++){
            for(let j=-3;j<=3;j++){
                if(i!==0&&j!==0){
                    let x=this.x+j;
                    let y=this.y+i;
                    if(!!this.room.map.boxes[y]&&this.room.map.boxes[y][x]===0&&!!this.room.map.obstacles[y]&&this.room.map.obstacles[y][x]===0&&!this.room.properties.find(item=>{return item.x===x&&item.y===y;})){
                        posArray.push({x:x,y:y});
                    }
                }
            }
        }
        posArray.sort( (a, b) => 0.5 - Math.random());
        //将爆出的道具放入空白点
        for(let i=0;i<properties.length;i++){
            if(!!posArray[i]){
                properties[i].x=posArray[i].x;
                properties[i].y=posArray[i].y;
                properties[i].setTimer();
                this.room.properties.push(properties[i]);
                result.push(properties[i].getMessage());
            }
        }
        return result;
    }
    //更改用户状态
    changeStatus(status){
        if(!this.room){return;}
        if(this.status!==status){
            this.status=status;
            if(status!==10){
                if(status===-1){
                    this.room.broadcastEvent('changeUserStatus',{index:this.index,x:this.x,y:this.y,status:status,properties:this.bombProperties()});
                }else{
                    this.room.broadcastEvent('changeUserStatus',{index:this.index,x:this.x,y:this.y,status:status});
                }
            }else{
                this.room.broadcastEvent('changeUserStatus',{index:this.index,x:this.x,y:this.y,status:status});
            }

        }
    }
    bindSocket(socket){
        if(!!this.socket){
            this._socketClose();
        }
        this.socket=socket;
        this.currentMessageCount=0;
        this.socket.on('close',function(){
            //链接断开时，退出匹配队列
            console.log('断开连接。');
            this._socketClose();
        }.bind(this));
        this.socket.on('method',function(dataObj){
            if(config.debug)
                console.log(`收到请求`,dataObj);
            if(!!this.room){
                this.room.queue.pushTry(function(){
                    this[dataObj.r](dataObj);
                }.bind(this));
            }else{
                if(dataObj.r=='ready'||dataObj.r=='createBomb'||dataObj.r=='setPos'||dataObj.r=='moveStop'||dataObj.r=='useThumbtack'){
                    return;
                }
                this.docker.queue.pushTry(function(){
                    this[dataObj.r](dataObj);
                }.bind(this));
            }
        }.bind(this));
    }
    _socketClose(){
        this.docker.queue.pushTry(function(){
            this.docker.exitOrder(this);
        }.bind(this));
        // this.docker.queue.pushTry(function(){
        //     //this.exitMatchingGroup();
        // }.bind(this));
        this.docker.queue.pushTry(function(){
            this.ready();
        }.bind(this));
        // this.docker.queue.pushTry(function(){
        //     // if(!!this.friendRoom){
        //     //     this.friendRoom.exit(this);
        //     // }
        // }.bind(this));
    }
    //加载游戏进度
    loadProcess(dataObj={process:'10%'}){
        if(!!this.room) //有可能这人还没加载完，游戏就已经结束了，房间已经不存在了
            this.room.broadcastEvent('loadProcess',{i:this.index,process:dataObj.process})
    }
    //创建组队
    async createMatchingGroup(dataObj={role:300}){
        this.role=dataObj.role;
        this.bombColor=dataObj.bombColor;
        let matchingGroup=this.docker.matchingGroups.find(item=>{return item.groupId==this._id});
        if(!matchingGroup){
            let hasDiamond=await this.checkDiamond(10);
            if(hasDiamond){
                const Group=require('./Group');
                matchingGroup=new Group(this.docker,this);
                this.docker.matchingGroups.push(matchingGroup);
            }
        }
    }
    //加入匹配小组
    async joinMatchingGroup(dataObj={groupId:'abc',role:300}){
        //let hasDiamond=await this.checkDiamond(10);
        //if(hasDiamond) {
        this.role=dataObj.role;
        this.bombColor=dataObj.bombColor;
        let matchingGroup = this.docker.matchingGroups.find(item => {
            return item.groupId == dataObj.groupId
        });
        if (!!matchingGroup) {
            matchingGroup.join(this);
        } else {
            this.sendEvent('joinMatchingGroupError', {});
        }
        //}
    }
    //退出匹配小组
    exitMatchingGroup(){
        if(!!this.matchingGroup){
            this.matchingGroup.exit(this);
        }
    }
    //小组匹配，一整组进行匹配
    matchingGroupMatching(){
        if(!!this.matchingGroup){
            this.docker.matchingGroupJoinOrder(this.matchingGroup.groupId);
        }
    }
    //创建好友房间
    async createFriendRoom(dataObj={role:1}){
        let friendRoom=this.docker.friendRooms.find(item=>{return item.id==this._id});
        if(!friendRoom){
            //let hasDiamond=await this.checkDiamond(10);
            //if(hasDiamond) {
                let FriendRoom = require('./FriendRoom');
                // this.role=dataObj.role;
                // this.bombColor=dataObj.bombColor;
                friendRoom = new FriendRoom(this.docker, this);
                this.docker.friendRooms.push(friendRoom);
                friendRoom.join(this);
           // }
        }else{
            console.log('该好友房存在，不能创建新的。。。');
            this.friendRoom=friendRoom;
            friendRoom.join(this);
            //this.sendEvent('friendRoomChange',friendRoom.getMessage());
        }
    }
    async joinFriendRoom(dataObj={id:'abc',role:300}){
        // this.role=dataObj.role;
        // this.bombColor=dataObj.bombColor;
        let friendRoom=this.docker.friendRooms.find(item=>{return item.id==dataObj.id});
        if(!!friendRoom){
            //let hasDiamond=await this.checkDiamond(10);
            //if(hasDiamond) {
            friendRoom.join(this);
            //}
        }else{
            let FriendRoom = require('./FriendRoom');
            friendRoom = new FriendRoom(this.docker, {_id:dataObj.id});
            this.docker.friendRooms.push(friendRoom);
            friendRoom.join(this);
            //this.sendEvent('friendRoomError',{msg:'好友房不存在！'});
        }
    }
    //退出好友房间，房主退出自动解散
    exitFriendRoom(){
        if(!!this.friendRoom){
            this.friendRoom.exit(this);
        }
    }

    //开始一个好友房的游戏
    startFriendRoom(dataObj={type:0}){
        if(this.friendRoom.id===this._id){
            this.friendRoom.gameStart(dataObj);
        }
    }
    //好友房踢人
    kickFriendRoomUser(dataObj={_id:'abc'}){
        if(!!this.friendRoom&&this.friendRoom.id===this._id){
            this.friendRoom.kick(dataObj._id);
        }
    }
    //换队伍
    exchangeFriendRoomTeam(){
        if(!!this.friendRoom){
            this.friendRoom.exchangeTeam(this);
        }
    }
    //进入匹配
    async matching(dataObj){
        if(!!this.room){return;}
        //let hasDiamond=await this.checkDiamond(10);
        //if(hasDiamond){
        // this.role = !!dataObj.role ? dataObj.role : 300;
        // this.bombColor=dataObj.bombColor;
        //console.log('dataObj:',dataObj);
        //this.thumbtackCount=!!dataObj.thumbtackCount?dataObj.thumbtackCount:0;
        this.docker.joinOrder(this);
        //此处加入随机库存用户显示
        this.send({e: 'matching',self:this.getMessage(),users:this.docker.getRandomUsers()});
       // }
    }
    //退出匹配
    exitMatching(){
        this.docker.exitOrder(this);
        this.send({e:'exitMatching'});
    }
    //创建泡泡
    createBomb(){
        if(this.status!==0||this.bombCount<=0){
            return;
        }
        //判断该位置能否创建泡泡
        let x=this.upX;
        let y=this.upY;
        if(this.room.bombs.findIndex(item=>{return item.x===x&&item.y===y})>=0){//!!this.room.map.bombs[y]&&!!this.room.map.bombs[y][x]){
            return;
        }
        let Bomb=require('./Bomb');
        // console.log('bombColor:',this.bombColor);
        let bomb=new Bomb({x:x,y:y,index:this.index,power:this.power,color:this.bombColor},this.room,this);
        this.bombCount--;
        bomb.i=this.room.currentBombId;
        this.room.currentBombId++;
        this.room.bombs.push(bomb);
        this.room.broadcastEvent('createBomb',bomb.getMessage());
    }
    //发送炸弹集体爆炸的变化时间，附加剩余的泡泡数量
    //data:前台附加计算出的炸弹爆炸点，箱子毁灭点，物品产生点
    sendBombChange(data){
        let obj={bombCount:this.bombCount};
        Object.assign(obj,data);
        this.sendEvent('bomb',obj);
    }
    clearTimers(){
        this.room.timerManager.clearTimeout(this.dieTimer);
    }
    //重置用户
    reset(){
        this.room=null;
        this.moveInterval=300;
        this.bombCount=2;
        this.thumbtackCount=0;
        this.power=1;
        this.status=0;
        this.isReady=false;
        this.properties=[];
    }
    send(obj){
        //obj.c=this.currentMessageCount;
        //this.currentMessageCount++;
        this.sendString(JSON.stringify(obj));
    }
    sendEvent(eventName,obj){
        let ob={e:eventName};
        Object.assign(ob,obj);
        this.send(ob);
        this.lastUpdateTick=new Date().getTime();
    }
    sendString(str,isLog=true){
        if(!!this.socket&&this.socket.readyState===1) {
            this.socket.send(str);
            if(config.debug&&isLog)
                console.log(`发送消息,nickname:${this.nickname},${str}`);
        }
    }
}

module.exports=User;